home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / batman.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  28KB  |  983 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/batman.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bits 13-15 = palette
  15.             Bits  0-12 = image number
  16.  
  17.  
  18.     Motion Object encoding
  19.     ----------------------
  20.         4 16-bit words are used
  21.  
  22.         Word 1:
  23.             Bits  0-7  = link to the next motion object
  24.  
  25.         Word 2:
  26.             Bits  0-11 = image index
  27.  
  28.         Word 3:
  29.             Bits  7-15 = horizontal position
  30.             Bits  0-3  = motion object palette
  31.  
  32.         Word 4:
  33.             Bits  7-15 = vertical position
  34.             Bits  4-6  = horizontal size of the object, in tiles
  35.             Bit   3    = horizontal flip
  36.             Bits  0-2  = vertical size of the object, in tiles
  37.  
  38.  
  39.     Alpha layer encoding
  40.     --------------------
  41.         1 16-bit word is used
  42.  
  43.         Word 1:
  44.             Bit  15    = transparent/opaque
  45.             Bit  10-13 = color
  46.             Bits  0-9  = index of the character
  47.  
  48. ***************************************************************************/
  49.  
  50. #include "driver.h"
  51. #include "machine/atarigen.h"
  52. #include "vidhrdw/generic.h"
  53.  
  54. #define XCHARS 42
  55. #define YCHARS 30
  56.  
  57. #define XDIM (XCHARS*8)
  58. #define YDIM (YCHARS*8)
  59.  
  60.  
  61. #define DEBUG_VIDEO 0
  62.  
  63.  
  64.  
  65. /*************************************
  66.  *
  67.  *    Structures
  68.  *
  69.  *************************************/
  70.  
  71. struct pf_overrender_data
  72. {
  73.     struct osd_bitmap *bitmap;
  74.     int mo_priority;
  75. };
  76.  
  77.  
  78.  
  79. /*************************************
  80.  *
  81.  *    Statics
  82.  *
  83.  *************************************/
  84.  
  85. static struct atarigen_pf_state pf_state;
  86. static struct atarigen_pf_state pf2_state;
  87.  
  88. static UINT16 alpha_bank;
  89.  
  90. #if DEBUG_VIDEO
  91. static UINT8 show_colors;
  92. static UINT8 special_pen;
  93. #endif
  94.  
  95.  
  96.  
  97. /*************************************
  98.  *
  99.  *    Prototypes
  100.  *
  101.  *************************************/
  102.  
  103. static const UINT8 *update_palette(void);
  104.  
  105. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  106. static void pf2_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  107. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  108. static void pf2_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  109. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  110. static void pf2_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  111.  
  112. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  113. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  114.  
  115. #if DEBUG_VIDEO
  116. static void debug(void);
  117. #endif
  118.  
  119.  
  120.  
  121. /*************************************
  122.  *
  123.  *    Video system start
  124.  *
  125.  *************************************/
  126.  
  127. int batman_vh_start(void)
  128. {
  129.     static struct atarigen_mo_desc mo_desc =
  130.     {
  131.         1024,                /* maximum number of MO's */
  132.         8,                   /* number of bytes per MO entry */
  133.         2,                   /* number of bytes between MO words */
  134.         0,                   /* ignore an entry if this word == 0xffff */
  135.         0, 0, 0x3ff,         /* link = (data[linkword] >> linkshift) & linkmask */
  136.         1                    /* reverse order */
  137.     };
  138.  
  139.     static struct atarigen_pf_desc pf_desc =
  140.     {
  141.         8, 8,                /* width/height of each tile */
  142.         64, 64                /* number of tiles in each direction */
  143.     };
  144.     
  145.     /* reset statics */
  146.     memset(&pf_state, 0, sizeof(pf_state));
  147.     memset(&pf2_state, 0, sizeof(pf2_state));
  148.     
  149.     /* initialize the playfield */
  150.     if (atarigen_pf_init(&pf_desc))
  151.         return 1;
  152.     
  153.     /* initialize the second playfield */
  154.     if (atarigen_pf2_init(&pf_desc))
  155.     {
  156.         atarigen_pf_free();
  157.         return 1;
  158.     }
  159.     
  160.     /* initialize the motion objects */
  161.     if (atarigen_mo_init(&mo_desc))
  162.     {
  163.         atarigen_pf2_free();
  164.         atarigen_pf_free();
  165.         return 1;
  166.     }
  167.     
  168.     return 0;
  169. }
  170.  
  171.  
  172.  
  173. /*************************************
  174.  *
  175.  *    Video system shutdown
  176.  *
  177.  *************************************/
  178.  
  179. void batman_vh_stop(void)
  180. {
  181.     atarigen_pf2_free();
  182.     atarigen_pf_free();
  183.     atarigen_mo_free();
  184. }
  185.  
  186.  
  187.  
  188. /*************************************
  189.  *
  190.  *    Alpha banking
  191.  *
  192.  *************************************/
  193.  
  194. void batman_set_alpha_bank(int bank)
  195. {
  196.     alpha_bank = bank * 0x400;
  197. }
  198.  
  199.  
  200.  
  201. /*************************************
  202.  *
  203.  *    Playfield RAM write handlers
  204.  *
  205.  *************************************/
  206.  
  207. WRITE_HANDLER( batman_colorram_w )
  208. {
  209.     int oldword = READ_WORD(&atarigen_playfieldram_color[offset]);
  210.     int newword = COMBINE_WORD(oldword, data);
  211.  
  212.     /* only update if changed */
  213.     if (oldword != newword)
  214.     {
  215.         WRITE_WORD(&atarigen_playfieldram_color[offset], newword);
  216.         
  217.         oldword ^= newword;
  218.         
  219.         /* low byte affects pf1 */
  220.         if (oldword & 0x00ff)
  221.             atarigen_pf_dirty[(offset / 2) & 0xfff] = 1;
  222.  
  223.         /* upper byte affects pf2 */
  224.         if (oldword & 0xff00)
  225.             atarigen_pf2_dirty[(offset / 2) & 0xfff] = 1;
  226.     }
  227. }
  228.  
  229.  
  230. WRITE_HANDLER( batman_playfieldram_w )
  231. {
  232.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  233.     int newword = COMBINE_WORD(oldword, data);
  234.  
  235.     /* only update if changed */
  236.     if (oldword != newword)
  237.     {
  238.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  239.         atarigen_pf_dirty[(offset / 2) & 0xfff] = 1;
  240.     }
  241.     
  242.     /* handle the latch, but only write the lower byte */
  243.     if (atarigen_video_control_state.latch2 != -1)
  244.         batman_colorram_w(offset, atarigen_video_control_state.latch2 | 0xff000000);
  245. }
  246.  
  247.  
  248. WRITE_HANDLER( batman_playfield2ram_w )
  249. {
  250.     int oldword = READ_WORD(&atarigen_playfield2ram[offset]);
  251.     int newword = COMBINE_WORD(oldword, data);
  252.  
  253.     /* only update if changed */
  254.     if (oldword != newword)
  255.     {
  256.         WRITE_WORD(&atarigen_playfield2ram[offset], newword);
  257.         atarigen_pf2_dirty[(offset / 2) & 0xfff] = 1;
  258.     }
  259.     
  260.     /* handle the latch, but only write the upper byte */
  261.     if (atarigen_video_control_state.latch1 != -1)
  262.         batman_colorram_w(offset, atarigen_video_control_state.latch1 | 0x00ff0000);
  263. }
  264.  
  265.  
  266.  
  267. /*************************************
  268.  *
  269.  *    Scroll register parser
  270.  *
  271.  *************************************/
  272.  
  273. static void recompute_scrolls_and_update(int scanline)
  274. {
  275.     /* copy in the scroll values */
  276.     pf_state.hscroll = atarigen_video_control_state.pf1_xscroll + (atarigen_video_control_state.pf2_xscroll & 7);
  277.     pf_state.vscroll = atarigen_video_control_state.pf1_yscroll;
  278.     pf2_state.hscroll = atarigen_video_control_state.pf2_xscroll + 4;
  279.     pf2_state.vscroll = atarigen_video_control_state.pf2_yscroll;
  280.     
  281.     /* update the two playfields */
  282.     atarigen_pf_update(&pf_state, scanline);
  283.     atarigen_pf2_update(&pf2_state, scanline);
  284. }
  285.  
  286.  
  287.  
  288. /*************************************
  289.  *
  290.  *    Periodic scanline updater
  291.  *
  292.  *************************************/
  293.  
  294. void batman_scanline_update(int scanline)
  295. {
  296.     /* update the screen parameters for the first scanline */
  297.     if (scanline == 0)
  298.     {
  299.         atarigen_video_control_update(&atarigen_alpharam[0xf00]);
  300.         recompute_scrolls_and_update(scanline);
  301.     }
  302.         
  303.     /* update the scanline parameters */
  304.     if (scanline < YDIM && atarigen_video_control_state.rowscroll_enable)
  305.     {
  306.         UINT8 *base = &atarigen_alpharam[2 * (scanline / 8 * 64 + 48)];
  307.         int i;
  308.         
  309.         for (i = 0; i < 8; i++, base += 4)
  310.         {
  311.             atarigen_video_control_w(0x20, READ_WORD(&base[0]));
  312.             atarigen_video_control_w(0x20, READ_WORD(&base[2]));
  313.             recompute_scrolls_and_update(scanline + 1 + i);
  314.         }
  315.     }
  316.  
  317.     /* update the MOs from the SLIP table */
  318.     atarigen_mo_update_slip_512(atarigen_spriteram, atarigen_video_control_state.sprite_yscroll, scanline, &atarigen_alpharam[0xf80]);
  319. }
  320.  
  321.  
  322.  
  323. /*************************************
  324.  *
  325.  *    Main refresh
  326.  *
  327.  *************************************/
  328.  
  329. void batman_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  330. {
  331.     int i;
  332.     
  333. #if DEBUG_VIDEO
  334.     debug();
  335. #endif
  336.  
  337.     /* update the palette */
  338.     if (update_palette())
  339.     {
  340.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 2);
  341.         memset(atarigen_pf2_dirty, 1, atarigen_playfield2ram_size / 2);
  342.     }
  343.  
  344.     /* set up the all-transparent overrender palette */
  345.     for (i = 0; i < 16; i++)
  346.         atarigen_overrender_colortable[i] = palette_transparent_pen;
  347.  
  348.     /* render the playfield */
  349.     memset(atarigen_pf_visit, 0, 64*64);
  350. #if DEBUG_VIDEO
  351.     if (show_colors == 2)
  352.         osd_clearbitmap(bitmap);
  353.     else
  354. #endif
  355.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  356.  
  357.     /* render the playfield */
  358.     memset(atarigen_pf2_visit, 0, 64*64);
  359. #if DEBUG_VIDEO
  360.     if (show_colors != 1)
  361. #endif
  362.     atarigen_pf2_process(pf2_render_callback, bitmap, &Machine->drv->visible_area);
  363.  
  364.     /* render the motion objects */
  365.     atarigen_mo_process(mo_render_callback, bitmap);
  366.  
  367.     /* redraw the alpha layer completely */
  368.     {
  369.         const struct GfxElement *gfx = Machine->gfx[2];
  370.         int sx, sy, offs;
  371.  
  372.         for (sy = 0; sy < YCHARS; sy++)
  373.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  374.             {
  375.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  376.                 int code = data & 0x3ff;
  377.                 int opaque = data & 0x8000;
  378.     
  379.                 if (data & 0x400) code += alpha_bank;
  380.                 if (code || opaque)
  381.                 {
  382.                     int color = (data >> 11) & 0xf;
  383.                     drawgfx(bitmap, gfx, code, color, 0, 0, 8 * sx, 8 * sy, 0,
  384.                             opaque ? TRANSPARENCY_NONE : TRANSPARENCY_PEN, 0);
  385.                 }
  386.             }
  387.     }
  388.  
  389.     /* update onscreen messages */
  390.     atarigen_update_messages();
  391. }
  392.  
  393.  
  394.  
  395. /*************************************
  396.  *
  397.  *    Palette management
  398.  *
  399.  *************************************/
  400.  
  401. static const UINT8 *update_palette(void)
  402. {
  403.     UINT16 mo_map[16], al_map[64], pf_map[32];
  404.     int i, j;
  405.  
  406.     /* reset color tracking */
  407.     memset(mo_map, 0, sizeof(mo_map));
  408.     memset(pf_map, 0, sizeof(pf_map));
  409.     memset(al_map, 0, sizeof(al_map));
  410.     palette_init_used_colors();
  411.     
  412.     /* update color usage for the playfields */
  413.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  414.     atarigen_pf2_process(pf2_color_callback, pf_map, &Machine->drv->visible_area);
  415.  
  416.     /* update color usage for the mo's */
  417.     atarigen_mo_process(mo_color_callback, mo_map);
  418.  
  419.     /* update color usage for the alphanumerics */
  420.     {
  421.         const unsigned int *usage = Machine->gfx[2]->pen_usage;
  422.         int sx, sy, offs;
  423.  
  424.         for (sy = 0; sy < YCHARS; sy++)
  425.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  426.             {
  427.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  428.                 int color = (data >> 11) & 0xf;
  429.                 int code = data & 0x3ff;
  430.     
  431.                 if (data & 0x400) code += alpha_bank;
  432.                 al_map[color] |= usage[code];
  433.             }
  434.     }
  435.  
  436.     /* rebuild the playfield palettes */
  437.     for (i = 0; i < 32; i++)
  438.     {
  439.         UINT16 used = pf_map[i];
  440.         if (used)
  441.         {
  442.             if (i < 16)
  443.                 palette_used_colors[0x200 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  444.             else if (used & 0x0001)
  445.                 palette_used_colors[0x200 + i * 16 + 0] = PALETTE_COLOR_USED;
  446.             for (j = 1; j < 16; j++)
  447.                 if (used & (1 << j))
  448.                     palette_used_colors[0x200 + i * 16 + j] = PALETTE_COLOR_USED;
  449.         }
  450.     }
  451.  
  452.     /* rebuild the motion object palette */
  453.     for (i = 0; i < 16; i++)
  454.     {
  455.         UINT16 used = mo_map[i];
  456.         if (used)
  457.         {
  458.             palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  459.             for (j = 1; j < 16; j++)
  460.                 if (used & (1 << j))
  461.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  462.         }
  463.     }
  464.  
  465.     /* rebuild the alphanumerics palette */
  466.     for (i = 0; i < 64; i++)
  467.     {
  468.         UINT16 used = al_map[i];
  469.         if (used)
  470.             for (j = 0; j < 4; j++)
  471.                 if (used & (1 << j))
  472.                     palette_used_colors[0x000 + i * 4 + j] = PALETTE_COLOR_USED;
  473.     }
  474.  
  475.     return palette_recalc();
  476. }
  477.  
  478.  
  479.  
  480. /*************************************
  481.  *
  482.  *    Playfield palette
  483.  *
  484.  *************************************/
  485.  
  486. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  487. {
  488.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  489.     UINT16 *colormap = param;
  490.     int x, y;
  491.     
  492.     /* standard loop over tiles */
  493.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  494.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  495.         {
  496.             int offs = x * 64 + y;
  497.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  498.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  499.             int code = data1 & 0x7fff;
  500.             int color = 0x10 + (data2 & 0x0f);
  501.  
  502.             /* mark the colors used by this tile */
  503.             colormap[color] |= usage[code];
  504.             
  505.             /* also mark unvisited tiles dirty */
  506.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 1;
  507.         }
  508. }
  509.  
  510.  
  511. static void pf2_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  512. {
  513.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  514.     UINT16 *colormap = param;
  515.     int x, y;
  516.     
  517.     /* standard loop over tiles */
  518.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  519.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  520.         {
  521.             int offs = x * 64 + y;
  522.             int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  523.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  524.             int code = data1 & 0x7fff;
  525.             int color = (data2 >> 8) & 0x0f;
  526.  
  527.             /* mark the colors used by this tile */
  528.             colormap[color] |= usage[code];
  529.             
  530.             /* also mark unvisited tiles dirty */
  531.             if (!atarigen_pf2_visit[offs]) atarigen_pf2_dirty[offs] = 1;
  532.         }
  533. }
  534.  
  535.  
  536.  
  537. /*************************************
  538.  *
  539.  *    Playfield rendering
  540.  *
  541.  *************************************/
  542.  
  543. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  544. {
  545.     const struct GfxElement *gfx = Machine->gfx[0];
  546.     struct osd_bitmap *bitmap = param;
  547.     int x, y;
  548.  
  549.     /* standard loop over tiles */
  550.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  551.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  552.         {
  553.             int offs = x * 64 + y;
  554.             
  555.             /* update only if dirty */
  556.             if (atarigen_pf_dirty[offs])
  557.             {
  558.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  559.                 int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  560.                 int color = 0x10 + (data2 & 0x0f);
  561.                 int code = data1 & 0x7fff;
  562.                 int hflip = data1 & 0x8000;
  563.                 
  564.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  565.                 atarigen_pf_dirty[offs] = 0;
  566.  
  567. #if DEBUG_VIDEO
  568.                 if (show_colors == 1 || show_colors == -1)
  569.                 {
  570.                     char c;
  571.                     if (show_colors == 1)
  572.                         c = "0123456789ABCDEF"[(data2 >> 4) & 0x0f];
  573.                     else
  574.                         c = "0123456789ABCDEF"[(data2 >> 0) & 0x0f];
  575.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  576.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  577.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  578.                 }
  579. #endif
  580.             }
  581.             
  582.             /* track the tiles we've visited */
  583.             atarigen_pf_visit[offs] = 1;
  584.         }
  585.  
  586.     /* then blast the result */
  587.     x = -state->hscroll;
  588.     y = -state->vscroll;
  589.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  590. }
  591.  
  592.  
  593. static void pf2_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  594. {
  595.     const struct GfxElement *gfx = Machine->gfx[0];
  596.     struct osd_bitmap *bitmap = param;
  597.     int x, y;
  598.  
  599.     /* standard loop over tiles */
  600.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  601.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  602.         {
  603.             int offs = x * 64 + y;
  604.             
  605.             /* update only if dirty */
  606.             if (atarigen_pf2_dirty[offs])
  607.             {
  608.                 int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  609.                 int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  610.                 int color = (data2 >> 8) & 0x0f;
  611.                 int code = data1 & 0x7fff;
  612.                 int hflip = data1 & 0x8000;
  613.                 
  614.                 drawgfx(atarigen_pf2_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  615.                 atarigen_pf2_dirty[offs] = 0;
  616.  
  617. #if DEBUG_VIDEO
  618.                 if (show_colors == 2 || show_colors == -2)
  619.                 {
  620.                     char c;
  621.                     if (show_colors == 2)
  622.                         c = "0123456789ABCDEF"[(data2 >> 12) & 0x0f];
  623.                     else
  624.                         c = "0123456789ABCDEF"[(data2 >> 8) & 0x0f];
  625.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  626.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  627.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  628.                 }
  629. #endif
  630.             }
  631.             
  632.             /* track the tiles we've visited */
  633.             atarigen_pf2_visit[offs] = 1;
  634.         }
  635.  
  636.     /* then blast the result */
  637.     x = -state->hscroll;
  638.     y = -state->vscroll;
  639.     copyscrollbitmap(bitmap, atarigen_pf2_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_PEN, palette_transparent_pen);
  640. }
  641.  
  642.  
  643.  
  644. /*************************************
  645.  *
  646.  *    Playfield overrendering
  647.  *
  648.  *************************************/
  649.  
  650. static const UINT16 transparency_mask[4] = { 0xffff, 0xff01, 0xff01, 0x0001 };
  651.  
  652. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  653. {
  654.     const struct pf_overrender_data *overrender_data = param;
  655.  
  656.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  657.     const struct GfxElement *gfx = Machine->gfx[0];
  658.     int mo_priority = overrender_data->mo_priority;
  659.     int x, y;
  660.  
  661.     /* standard loop over tiles */
  662.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  663.     {
  664.         int sx = (8 * x - state->hscroll) & 0x1ff;
  665.         if (sx >= XDIM) sx -= 0x200;
  666.  
  667.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  668.         {
  669.             int offs = x * 64 + y;
  670.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  671.             int priority = (data2 >> 4) & 3;
  672.             
  673.             if (priority > mo_priority)
  674.             {
  675.                 int color = 0x10 + (data2 & 0x0f);
  676.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  677.                 int code = data1 & 0x7fff;
  678.                 int hflip = data1 & 0x8000;
  679.  
  680.                 int sy = (8 * y - state->vscroll) & 0x1ff;
  681.                 if (sy >= YDIM) sy -= 0x200;
  682.  
  683.                 if (mo_priority == -1)
  684.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  685. #if DEBUG_VIDEO
  686.                 else if (special_pen != -1)
  687.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, ~(1 << special_pen));
  688. #endif
  689.                 else
  690.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, transparency_mask[priority]);
  691.             }
  692.         }
  693.     }
  694. }
  695.  
  696.  
  697. static void pf2_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  698. {
  699.     const struct pf_overrender_data *overrender_data = param;
  700.  
  701.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  702.     const struct GfxElement *gfx = Machine->gfx[0];
  703.     int mo_priority = overrender_data->mo_priority;
  704.     int x, y;
  705.  
  706.     /* standard loop over tiles */
  707.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  708.     {
  709.         int sx = (8 * x - state->hscroll) & 0x1ff;
  710.         if (sx >= XDIM) sx -= 0x200;
  711.  
  712.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  713.         {
  714.             int offs = x * 64 + y;
  715.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  716.             int priority = (data2 >> 12) & 3;
  717.             
  718.             if (priority > mo_priority)
  719.             {
  720.                 int color = (data2 >> 8) & 0x0f;
  721.                 int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  722.                 int code = data1 & 0x7fff;
  723.                 int hflip = data1 & 0x8000;
  724.  
  725.                 int sy = (8 * y - state->vscroll) & 0x1ff;
  726.                 if (sy >= YDIM) sy -= 0x200;
  727.             
  728.                 if (mo_priority == -1)
  729.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  730. #if DEBUG_VIDEO
  731.                 else if (special_pen != -1)
  732.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, ~(1 << special_pen));
  733. #endif
  734.                 else
  735.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, transparency_mask[priority]);
  736.             }
  737.         }
  738.     }
  739. }
  740.  
  741.  
  742.  
  743. /*************************************
  744.  *
  745.  *    Motion object palette
  746.  *
  747.  *************************************/
  748.  
  749. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  750. {
  751.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  752.     UINT16 *colormap = param;
  753.     int code = data[1] & 0x7fff;
  754.     int color = data[2] & 0x000f;
  755.     int hsize = ((data[3] >> 4) & 7) + 1;
  756.     int vsize = (data[3] & 7) + 1;
  757.     int tiles = hsize * vsize;
  758.     UINT16 temp = 0;
  759.     int i;
  760.  
  761.     for (i = 0; i < tiles; i++)
  762.         temp |= usage[code++];
  763.     colormap[color] |= temp;
  764. }
  765.  
  766.  
  767.  
  768. /*************************************
  769.  *
  770.  *    Motion object rendering
  771.  *
  772.  *************************************/
  773.  
  774. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  775. {
  776.     struct GfxElement *gfx = Machine->gfx[1];
  777.     struct pf_overrender_data overrender_data;
  778.     struct osd_bitmap *bitmap = param;
  779.     struct rectangle pf_clip;
  780.  
  781.     /* extract data from the various words */
  782.     int hflip = data[1] & 0x8000;
  783.     int code = data[1] & 0x7fff;
  784.     int xpos = (data[2] >> 7) - atarigen_video_control_state.sprite_xscroll;
  785.     int priority = (data[2] >> 4) & 7;
  786.     int color = data[2] & 0x000f;
  787.     int ypos = -(data[3] >> 7) - atarigen_video_control_state.sprite_yscroll;
  788.     int hsize = ((data[3] >> 4) & 7) + 1;
  789.     int vsize = (data[3] & 7) + 1;
  790.  
  791.     /* adjust for height */
  792.     ypos -= vsize * 8;
  793.  
  794.     /* adjust the final coordinates */
  795.     xpos &= 0x1ff;
  796.     ypos &= 0x1ff;
  797.     if (xpos >= XDIM) xpos -= 0x200;
  798.     if (ypos >= YDIM) ypos -= 0x200;
  799.  
  800.     /* determine the bounding box */
  801.     atarigen_mo_compute_clip_8x8(pf_clip, xpos, ypos, hsize, vsize, clip);
  802.  
  803.     /* simple case? */
  804.     if (priority == 3)
  805.     {
  806.         /* just draw -- we have dominion over all */
  807.         atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  808.     }
  809.  
  810. #if DEBUG_VIDEO
  811.     else if (show_colors)
  812.     {
  813.         atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  814.     }
  815. #endif
  816.  
  817.     /* otherwise, it gets a smidge trickier */
  818.     else
  819.     {
  820.         /* draw an instance of the object in all transparent pens */
  821.         atarigen_mo_draw_transparent_8x8(bitmap, gfx, code, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  822.  
  823.         /* start by recopying the background to the temp bitmap */
  824.         atarigen_pf_process(pf_overrender_callback, atarigen_pf_overrender_bitmap, &pf_clip);
  825.  
  826.         /* and then draw the M.O. normally on top of it */
  827.         atarigen_mo_draw_8x8(atarigen_pf_overrender_bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  828.  
  829.         /* overrender the playfields on top of that */
  830.         overrender_data.mo_priority = priority;
  831.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  832.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  833.         atarigen_pf2_process(pf2_overrender_callback, &overrender_data, &pf_clip);
  834.  
  835.         /* finally, copy this chunk to the real bitmap */
  836.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  837.     }
  838.  
  839. #if DEBUG_VIDEO
  840.     if (show_colors)
  841.     {
  842.         int tx = (pf_clip.min_x + pf_clip.max_x) / 2 - 3;
  843.         int ty = (pf_clip.min_y + pf_clip.max_y) / 2 - 4;
  844.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  845.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  846.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  847.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  848.         drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[priority], 0, 0, 0, tx, ty, 0, TRANSPARENCY_NONE, 0);
  849.     }
  850. #endif
  851. }
  852.  
  853.  
  854.  
  855. /*************************************
  856.  *
  857.  *    Debugging
  858.  *
  859.  *************************************/
  860.  
  861. #if DEBUG_VIDEO
  862.  
  863. static void debug(void)
  864. {
  865.     int new_show_colors;
  866.     
  867.     new_show_colors = (keyboard_pressed(KEYCODE_LSHIFT)) ? 1 : keyboard_pressed(KEYCODE_RSHIFT) ? 2 : 0;
  868.     if (new_show_colors != show_colors)
  869.     {
  870.         show_colors = new_show_colors;
  871.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  872.         memset(atarigen_pf2_dirty, 0xff, atarigen_playfieldram_size / 2);
  873.     }
  874.  
  875.     special_pen = -1;
  876.     if (keyboard_pressed(KEYCODE_Q)) special_pen = 0;
  877.     if (keyboard_pressed(KEYCODE_W)) special_pen = 1;
  878.     if (keyboard_pressed(KEYCODE_E)) special_pen = 2;
  879.     if (keyboard_pressed(KEYCODE_R)) special_pen = 3;
  880.     if (keyboard_pressed(KEYCODE_T)) special_pen = 4;
  881.     if (keyboard_pressed(KEYCODE_Y)) special_pen = 5;
  882.     if (keyboard_pressed(KEYCODE_U)) special_pen = 6;
  883.     if (keyboard_pressed(KEYCODE_I)) special_pen = 7;
  884.  
  885.     if (keyboard_pressed(KEYCODE_A)) special_pen = 8;
  886.     if (keyboard_pressed(KEYCODE_S)) special_pen = 9;
  887.     if (keyboard_pressed(KEYCODE_D)) special_pen = 10;
  888.     if (keyboard_pressed(KEYCODE_F)) special_pen = 11;
  889.     if (keyboard_pressed(KEYCODE_G)) special_pen = 12;
  890.     if (keyboard_pressed(KEYCODE_H)) special_pen = 13;
  891.     if (keyboard_pressed(KEYCODE_J)) special_pen = 14;
  892.     if (keyboard_pressed(KEYCODE_K)) special_pen = 15;
  893.     
  894.     if (keyboard_pressed(KEYCODE_9))
  895.     {
  896.         static int count;
  897.         char name[50];
  898.         FILE *f;
  899.         int i;
  900.  
  901.         while (keyboard_pressed(KEYCODE_9)) { }
  902.  
  903.         sprintf(name, "Dump %d", ++count);
  904.         f = fopen(name, "wt");
  905.  
  906.         fprintf(f, "\n\nAlpha Palette:\n");
  907.         for (i = 0x000; i < 0x100; i++)
  908.         {
  909.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  910.             if ((i & 15) == 15) fprintf(f, "\n");
  911.         }
  912.  
  913.         fprintf(f, "\n\nMotion Object Palette:\n");
  914.         for (i = 0x100; i < 0x200; i++)
  915.         {
  916.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  917.             if ((i & 15) == 15) fprintf(f, "\n");
  918.         }
  919.  
  920.         fprintf(f, "\n\nPlayfield Palette:\n");
  921.         for (i = 0x200; i < 0x400; i++)
  922.         {
  923.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  924.             if ((i & 15) == 15) fprintf(f, "\n");
  925.         }
  926.  
  927.         fprintf(f, "\n\nMotion Object Config:\n");
  928.         for (i = 0x00; i < 0x40; i++)
  929.         {
  930.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[0xf00 + i*2]));
  931.             if ((i & 15) == 15) fprintf(f, "\n");
  932.         }
  933.  
  934.         fprintf(f, "\n\nMotion Object SLIPs:\n");
  935.         for (i = 0x00; i < 0x40; i++)
  936.         {
  937.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[0xf80 + i*2]));
  938.             if ((i & 15) == 15) fprintf(f, "\n");
  939.         }
  940.  
  941.         fprintf(f, "\n\nMotion Objects\n");
  942.         for (i = 0; i < 0x400; i++)
  943.         {
  944.             UINT16 *data = (UINT16 *)&atarigen_spriteram[i*8];
  945.             int code = data[1] & 0x7fff;
  946.             int hsize = ((data[3] >> 4) & 7) + 1;
  947.             int vsize = (data[3] & 7) + 1;
  948.             int xpos = (data[2] >> 7);
  949.             int ypos = (data[3] >> 7) - vsize * 8;
  950.             int color = data[2] & 15;
  951.             int hflip = data[3] & 0x0008;
  952.             fprintf(f, "   Object %03X: L=%03X P=%04X C=%X X=%03X Y=%03X W=%d H=%d F=%d LEFT=(%04X %04X %04X %04X)\n",
  953.                     i, data[0] & 0x3ff, code, color, xpos & 0x1ff, ypos & 0x1ff, hsize, vsize, hflip,
  954.                     data[0] & 0xfc00, data[1] & 0x0000, data[2] & 0x0070, data[3] & 0x0000);
  955.         }
  956.  
  957.         fprintf(f, "\n\nPlayfield 1 dump\n");
  958.         for (i = 0; i < atarigen_playfieldram_size / 2; i++)
  959.         {
  960.             fprintf(f, "%X%04X ", READ_WORD(&atarigen_playfieldram_color[i*2]) & 0xff, READ_WORD(&atarigen_playfieldram[i*2]));
  961.             if ((i & 63) == 63) fprintf(f, "\n");
  962.         }
  963.  
  964.         fprintf(f, "\n\nPlayfield 2 dump\n");
  965.         for (i = 0; i < atarigen_playfield2ram_size / 2; i++)
  966.         {
  967.             fprintf(f, "%X%04X ", (READ_WORD(&atarigen_playfieldram_color[i*2]) >> 8) & 0xff, READ_WORD(&atarigen_playfield2ram[i*2]));
  968.             if ((i & 63) == 63) fprintf(f, "\n");
  969.         }
  970.  
  971.         fprintf(f, "\n\nAlpha dump\n");
  972.         for (i = 0; i < atarigen_alpharam_size / 2; i++)
  973.         {
  974.             fprintf(f, "%04X ", READ_WORD(&atarigen_alpharam[i*2]));
  975.             if ((i & 63) == 63) fprintf(f, "\n");
  976.         }
  977.  
  978.         fclose(f);
  979.     }
  980. }
  981.  
  982. #endif
  983.